using System;
using System.Collections;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using ctsu.Admin.BusLogic.CoreLab;
using Microsoft.Practices.EnterpriseLibrary.Data;

using Syncfusion.Windows.Forms.Grid;
using Syncfusion.Windows.Forms.Tools;
using ctsu.Admin.Forms;
using ctsu.BaseForms;
using ctsu.Security;
using ctsu.Shared;
using ctsu.Data;

namespace ctsu.Admin.BusLogic
{
	class BLFormOffUnitActivityImpl : BLFormBaseImpl
	{
		DateTime _originalWorkDate;  //used only if in edit
		#region control references
		protected NumericUpDown _patients;
		protected ComboBox _coordinator;
		protected DateTimePickerAdv _workDate;
		protected ComboBox _protocolLook;
		protected ComboBox _activityLook;
		protected DoubleTextBox _duration;
		private Button _btnAddBatch;
		//private Button _btnEditBatch;        
		private Button _btnRemoveBatch;
		#endregion control references

		public BLFormOffUnitActivityImpl(FormMain formMain, FormBase form, FormInfoBase formInfo, DataTable tableSchema, Permission formSecurity, Hashtable configData)
			: base(formMain, form, formInfo, tableSchema, formSecurity, configData)
		{

		}
		protected override void _vcManager_OnAfterHookEvents()
		{
			base._vcManager_OnAfterHookEvents();
			_coordinator = (ComboBox)Forms.Utils.GetControlByName("Coordinator", this._form.Controls);
			_workDate = (DateTimePickerAdv)Forms.Utils.GetControlByName("WorkDate", this._form.Controls);
			_protocolLook = (ComboBox)Forms.Utils.GetControlByName("ProtocolLook", this._form.Controls);
			_activityLook = (ComboBox)Forms.Utils.GetControlByName("ActivityLook", this._form.Controls);
			_duration = (DoubleTextBox)Forms.Utils.GetControlByName("Duration", this._form.Controls);
			_btnAddBatch = (Button)Forms.Utils.GetControlByName("btnAddBatch", this._form.Controls);
			_patients = (NumericUpDown)Forms.Utils.GetControlByName("Patients", this._form.Controls);
			//_btnEditBatch = (Button)Forms.Utils.GetControlByName("btnEditBatch", this._form.Controls);       
			_btnRemoveBatch = (Button)Forms.Utils.GetControlByName("btnRemoveBatch", this._form.Controls);

		}

		protected override bool FillSpecialLookups()
		{
			StringBuilder sb = new StringBuilder();
			try
			{
				foreach (SpecialLookup sl in _formInfo.SpecialLookups.Values)
				{
					Control ctl = ctsu.Admin.Forms.Utils.GetControlByName(sl.FieldName, this._form.Controls);
					if (sl.GridName.Length > 0)
						continue;
					if (sl.FieldName == "ProtocolLook")
						LoadCbo(sl, ctl);
					else
						ctsu.Admin.Forms.Utils.LoadCbo(sl, ctl);
				}

			}
			catch (Exception ex)
			{
				sb.Append("Could not load special lookups!");
				sb.Append(Environment.NewLine);
				sb.Append("Error message: " + ex.Message);
				//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
				MessageBox.Show(this._form, sb.ToString(), "Loading Special Lookups Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			}
			return true;
		}

		private void LoadCbo(BaseForms.SpecialLookup sl, Control ctl)
		{
			NameVal nv;
			ComboBox cbo = (ComboBox)ctl;
			ArrayList al = new ArrayList();

			string sql = "SELECT " + sl.DisplayField + "," +
				sl.ValueField + " FROM " + sl.TableName;

			if (sl.WhereClause.Length > 0)
				sql += " WHERE " + sl.WhereClause;

			if (sl.OrderField.Length > 0)
				sql += " ORDER BY " + sl.OrderField;

			//SqlConnection conn = LoginForm.GetSqlConnection();
			IDataReader reader = null;
			try
			{
				reader = Data.DataAccess.GetDataReader(sql);
				cbo.BeginUpdate();

				string sVal;
				int iVal;
				while (reader.Read())
				{
					if (reader.IsDBNull(0))
						continue;
					sVal = reader.GetString(0);

					iVal = reader.GetInt32(1);

					Console.WriteLine("Val:" + iVal);
					nv = new NameVal(iVal, sVal);
					al.Add(nv);
				}


				nv = new NameVal(0, "pre-approved");
				al.Insert(0, nv);

				cbo.DataSource = al;
				cbo.DisplayMember = "Name";
				cbo.ValueMember = "Val";
				cbo.EndUpdate();
			}
			catch
			{
				throw;
			}
			finally
			{
				if (reader != null)
					reader.Close();
				//if(conn != null)
				//    conn.Dispose();				
			}
		}

		public override void Edit()
		{
			base.Edit();
			_coordinator.Enabled = false;
			_originalWorkDate = _workDate.Value;
		}

		public override void New()
		{
			base.New();
			_patients.Value = 0;
			_duration.Text = "0.0";
		}

		protected override void SetControlsEnabled(bool enable)
		{
			base.SetControlsEnabled(enable);

			_btnAddBatch.Enabled = enable; ;
			_btnRemoveBatch.Enabled = enable;
			_protocolLook.Enabled = enable;
			_activityLook.Enabled = enable;
			_duration.Enabled = enable;
			_patients.Enabled = enable;

		}

		public override bool Save()
		{
			StringBuilder sb = new StringBuilder();
			string message = "";

			//this is used as a parameter for table grid display
			//DbTableChange tableChange = DbTableChange.Update;

			if (this._doSummaryValidate)
			{
				if (!VerifyAll())
					return false;
				if (!VerifyGrids())
					return false;
			}

			Console.WriteLine("RowState brfore save: " + this._fcManager.CurrentRow.RowState.ToString());
			Database db = DatabaseFactory.CreateDatabase();
			using (DbConnection conn = db.CreateConnection())
			{
				try
				{
					conn.Open();
					DbTransaction trans = conn.BeginTransaction();

					if (_formMode == EditMode.New)
					{
						if (CheckDuplicate())
							return false;
						if (CheckWarning())
							return false;
						//tableChange = DbTableChange.Insert;
						if (!SaveNew(out message, db, trans))
						{
							trans.Rollback();
							sb.Append("New record for " + this._formInfo.Name + " could not be saved.");
							sb.Append(Environment.NewLine);
							sb.Append("Error: " + message);
							MessageBox.Show(this._form, sb.ToString(), "Save Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
							return false;
						}

					}
					else if (_formMode == EditMode.Edit)
					{
						if (_originalWorkDate.CompareTo(_workDate.Value) != 0)
						{
							if (CheckDuplicate())
								return false;
						}

						if (!Update(out message, db, trans))
						{
							trans.Rollback();
							sb.Append("Update for " + this._formInfo.Name + " could not be saved.");
							sb.Append(Environment.NewLine);
							sb.Append("Error: " + message);
							MessageBox.Show(this._form, sb.ToString(), "Save Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
							return false;
						}
					}

					if (this._gridBLs != null)
					{
						if (!SaveGrids(out message, db, trans))
						{
							trans.Rollback();
							sb.Append("Grid data " + this._formInfo.Name + " could not be saved.");
							sb.Append(Environment.NewLine);
							sb.Append("Error: " + message);
							MessageBox.Show(this._form, sb.ToString(), "Save Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
							return false;
						}
					}

					trans.Commit();
					ResetGrids();
					//confirmation dialog
					MessageBox.Show("Record was saved.", "Save Confirmation",
						MessageBoxButtons.OK, MessageBoxIcon.Information);

					bool shouldClose = (bool)this._configData["CloseOnSave"];

					if (shouldClose)
					{
						this._isClosing = true;
						this._form.Close();
					}
					else
					{
						this._fcManager.CurrentRow.AcceptChanges();
						SetGridsAcceptChanges();
						SetFormMode(EditMode.Read);
					}
					//BLTableChangeAdvEventArgs args = new BLTableChangeAdvEventArgs(this._formInfo.TableName, tableChange, this._currentPrimaryID - 1);

					//this.TableChange(this._form, args);
					this.FireTableChange(DbTableChange.Update);
					Console.WriteLine("RowState after save: " + this._fcManager.CurrentRow.RowState.ToString());
					this.CarryNewClicked(_chkCarry);

					return true;
				}
				catch (Exception ex)
				{
					//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
					sb.Append("Form could not be saved.");
					sb.Append(Environment.NewLine);
					sb.Append("Error message: " + ex.Message);
					MessageBox.Show(this._form, sb.ToString(), "Save Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return false;
				}
			}
		}


		protected override bool CheckDuplicate()
		{
			StringBuilder sb = new StringBuilder();
			int iCoord = (int)_coordinator.SelectedValue;
			DateTime dt = _workDate.Value;

			string sql = "SELECT Count(ID) FROM OffUnitCoordDays " +
				" WHERE Coordinator=" + iCoord +
				" AND WorkDate ='" + dt.ToShortDateString() + "'";

			//SqlConnection conn = LoginForm.GetSqlConnection();
			try
			{
				int i = (int)DataAccess.GetScalarObject(CommandType.Text, sql);
				if (i > 0)
				{
					sb.Append("You already have activities for this work date.");
					sb.Append(Environment.NewLine);
					sb.Append("Duplicate work dates are not allowed.");
					MessageBox.Show(this._form, sb.ToString(), "Duplicate Work Date", MessageBoxButtons.OK, MessageBoxIcon.Stop);
					return true;
				}
				return false;
			}
			catch (Exception ex)
			{
				sb.Append("Could not check for duplicates!");
				sb.Append(Environment.NewLine);
				sb.Append("Error message: " + ex.Message);
				//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
				MessageBox.Show(this._form, sb.ToString(), "Check Duplicates Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return true;
			}
			finally
			{
				//if(conn != null)
				//    conn.Dispose();
			}
		}

		protected override bool InitializeGrid(FormGridMeta fgm)
		{
			GridControl grd = (GridControl)Forms.Utils.GetControlByName(fgm.GridName, this._form.Controls);
			//capture double click here too
			grd.CellDoubleClick += new GridCellClickEventHandler(grd_CellDoubleClick);

			//FormGridMeta formGridMeta, UserGrid uGrid, FormInfoBase formInfo, FormBase form
			Type[] argTypes = new Type[4];
			argTypes[0] = typeof(FormGridMeta);
			argTypes[1] = typeof(GridControl);
			argTypes[2] = typeof(FormInfoBase);
			argTypes[3] = typeof(FormBase);

			object[] args = new object[4];
			args[0] = fgm;
			args[1] = grd;
			args[2] = _formInfo;
			args[3] = _form; //security permission

			//invoke creation of bl
			Type grdBL = Type.GetType("ctsu.Admin.BusLogic." + fgm.BusinessLogicClassName);

			ConstructorInfo info = grdBL.GetConstructor(argTypes);
			IBLCoreLabFormGridBase fgbl = (IBLCoreLabFormGridBase)info.Invoke(args);
			fgbl.GridColumnValueChanged += new ctsu.BaseForms.BusinessLogicEvents.BLGridColumnValueChangedHandler(fgbl_GridColumnValueChanged);
			fgbl.GridValidateError += new ctsu.BaseForms.BusinessLogicEvents.BLGridValidateErrorEventHandler(fgbl_GridValidateError);

			if (!fgbl.Initialize())
				return false;
			_gridBLs.Add(fgm.GridName, fgbl);
			return true;
		}

		private void grd_CellDoubleClick(object sender, GridCellClickEventArgs e)
		{
			Console.WriteLine("grd_CellDoubleClick");
		}

		protected override void SetGridsEnabled(bool enable)
		{
			SetCoreLabGridsEnabled(enable);
		}

		protected virtual void SetCoreLabGridsEnabled(bool enable)
		{
			foreach (BLCoreLabFormGridBaseImpl fgbl in _gridBLs.Values)
			{
				fgbl.SetEnabled(enable);
			}
		}

		protected override bool GetGridData(int id)
		{
			if (this._gridBLs != null)
			{
				foreach (BLCoreLabFormGridBaseImpl fgbl in this._gridBLs.Values)
				{
					if (!fgbl.GetData(id))
					{
						//TODO - need to do more here for exception							
						MessageBox.Show("GetGridData Exception");
						return false;
					}
				}
			}
			return true;
		}

		protected override void SetGridsNew()
		{
			//notify the grids there is a new form record
			if (this._gridBLs != null)
			{
				foreach (BLCoreLabFormGridBaseImpl bl in this._gridBLs.Values)
					bl.New();
			}
		}

		#region save
		protected override bool VerifyGrids()
		{
			if (this._gridBLs != null)
			{
				foreach (BLCoreLabFormGridBaseImpl fgbl in this._gridBLs.Values)
					if (!fgbl.VerifyGrid())
						return false;
			}
			return true;
		}

		protected override void SetGridsAcceptChanges()
		{
			foreach (BLCoreLabFormGridBaseImpl bl in this._gridBLs.Values)
			{
				bl.AcceptChanges();
			}
		}

		protected override bool SaveGrids(out string message, Microsoft.Practices.EnterpriseLibrary.Data.Database db, DbTransaction trans)
		{
			message = "";
			foreach (BLCoreLabFormGridBaseImpl bl in this._gridBLs.Values)
			{
				if (!bl.Save(this._currentPrimaryID, out message, db, trans))
					return false;
				//resets data to show new id's
				//bl.GetData(this._currentPrimaryID);				
			}
			return true;
		}

		protected override void ResetGrids()
		{
			ResetCoreLabGrids();
		}
		protected virtual void ResetCoreLabGrids()
		{
			foreach (BLCoreLabFormGridBaseImpl fgbl in _gridBLs.Values)
				fgbl.Reset(this._formMode, _currentPrimaryID);
		}
		#endregion save

		public override void GenericClick(Control sender)
		{
			if (sender.Name == "btnAddBatch")
				AddToBatch();
			//if (sender.Name == "btnEditBatch")
			//    EditBatch();
			if (sender.Name == "btnRemoveBatch")
				RemoveBatch();
			if (sender.Name == "btnPrint")
				DoPrint();
		}

		private void DoPrint()
		{

		}

		#region remove batch
		private void RemoveBatch()
		{
			GridControl grid = (GridControl)Forms.Utils.GetControlByName("Activities", this._form.Controls);

			GridRangeInfoList list;
			list = grid.Selections.GetSelectedRows(true, false);
			if (list.Count == 0)
				return;

			BLCoreLabFormGridBaseImpl fgbl = (BLCoreLabFormGridBaseImpl)this._gridBLs["Activities"];

			ArrayList alRows = new ArrayList();
			int row = 0;
			int top = 0;
			int bottom = 0;
			for (int i = 0; i < list.Count; i++)
			{
				top = list[i].Top;
				bottom = list[i].Bottom;
				if (bottom > top)
					GetSelectedRows(alRows, top, bottom);
				else
					alRows.Add(list[i].Top);
			}
			for (int i = 0; i < alRows.Count; i++)
			{
				row = (int)alRows[i];
				row -= i;
				DataRow dr = (DataRow)fgbl.Grid[row, 0].Tag;
				dr.RejectChanges();
				fgbl.RemoveRow(row);
			}
			this._form.btnSave.Enabled = true;
		}

		private void GetSelectedRows(ArrayList alRows, int top, int bottom)
		{
			int rows = bottom - top + 1;
			for (int i = 0; i < rows; i++)
				alRows.Add(top + i);
		}
		#endregion remove batch


		private void AddToBatch()
		{
			if (VerifyAddToBatch())
			{
				IBLCoreLabFormGridBase fgbl = (IBLCoreLabFormGridBase)this._gridBLs["Activities"];
				OffUnitActivity act = new OffUnitActivity();
				act.ProtocolID = (int)_protocolLook.SelectedValue;
				act.ActivityID = (int)_activityLook.SelectedValue;
				act.Duration = double.Parse(_duration.Text);
				act.Patients = int.Parse(_patients.Value.ToString());
				fgbl.AddRow(act, 0);
			}

		}

		private bool VerifyAddToBatch()
		{
			double dbl = double.Parse(_duration.Text);
			if (dbl == 0)
			{
				MessageBox.Show(this._form, "Duration must be greater than 0", "Duration Is Invalid", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				return false;
			}

			if (!(_duration.Text.EndsWith("0") || _duration.Text.EndsWith("5")))
			{
				MessageBox.Show(this._form, "The decimal must be .0 or .5 for duration", "Duration Is Invalid", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				return false;
			}
			return true;
		}

		protected bool VerifyCoordinator(Control ctl)
		{
			bool retVal = true;
			ComboBox cbo = (ComboBox)ctl;
			FieldContext fc = (FieldContext)ctl.Tag;

			Console.WriteLine("VerifyCombo,Control: " + ctl.Name);

			if (fc.Manager.CurrentRow == null)
				return true;

			Console.WriteLine("CurrentValue: " + fc.CurrentValue.ToString());

			if ((int)fc.CurrentValue == -1)
			{
				if (fc.IsRequired)
				{
					fc.ErrorMessage = Constants.ValidErrorRequiredEmpty;
					retVal = false;
				}

			}
			else
			{
				fc.ErrorMessage = "";
			}

			Console.WriteLine("Column Changed = " + fc.IsColumnChanged(fc.Column.ColumnName).ToString());

			Console.WriteLine("ErrorMessage: " + fc.ErrorMessage);
			Console.WriteLine("Return Value: " + retVal.ToString());

			return retVal;
		}


	}



	public class OffUnitActivity
	{
		public OffUnitActivity()
		{
		}

		public int ProtocolID;
		public string ProtocolNumber;
		public int ActivityID;
		public string ActivityName;
		public double Duration;
		public int Patients;
	}
}
